#ifndef __TROPHY_EDIT_WINDOW_H__
#define __TROPHY_EDIT_WINDOW_H__

#include <stdio.h>
#include "../SimpleWnd/SimpleWnd.h"
#include "../SimpleWnd/SimpleTipCtrl.h"
#include "../SplitterWnd.h"
#include "TextDoc.h"
#include "EditStack.h"
#include "FindReplaceDlg.h"
#include "HiliteConfig.h"
#include "Lighter.h"


#define EDIT_WND_CLASS "TROPHY SOURCE FILE EDIT"

/* 
 * Only supports fixed width fonts.
 */
#define DEFAULT_SYNTAXFILE "syntax.hilight"
enum DragMode 
{
    NoDrag, DragMove, DragCopy
};

#define DEBUG_LINE_COLOR    RGB(255,255,0)
#define BREAKPOINT_COLOR    RGB(255,128,0)

class IDebuggerIF2Editor
{
public:
   virtual void GetCurRtnLineNoRange(int* nStart, int* nEnd) = 0;
   /*
    * If the var is found, teh value is copied in buf as a string, and return 0.
    *  if the var is not found, returns negative value.
    */
   virtual int GetVaribleValueInCurRtn(LPCTSTR var, TCHAR* buf, size_t size)= 0;
};

class CEditWindow : public IPaneWindow, 
                    public CWnd,
                    public IFindReplaceHost
{
public:
    DECLARE_WND_CLASS_EX(EDIT_WND_CLASS, CS_DBLCLKS, COLOR_WINDOW)

    CEditWindow();
    virtual ~CEditWindow();

BEGIN_MSG_MAP(CEditWindow)
    MESSAGE_HANDLER(WM_CREATE, OnCreate)
    MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
    MESSAGE_HANDLER(WM_SIZE, OnSize)
    MESSAGE_HANDLER(WM_PAINT, OnPaint)
    MESSAGE_HANDLER(WM_HSCROLL, OnScroll)
    MESSAGE_HANDLER(WM_VSCROLL, OnScroll)
    MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
    MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
    MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLBtnDown)
    MESSAGE_HANDLER(WM_LBUTTONUP, OnLBtnUp)
    MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnDblClk)
    MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
    MESSAGE_HANDLER(WM_RBUTTONDOWN, OnRBtnDown)
    MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
    MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
    MESSAGE_HANDLER(WM_KEYUP, OnKeyUp)
    MESSAGE_HANDLER(WM_CHAR, OnChar)
    MESSAGE_HANDLER(WM_IME_COMPOSITION, OnImeComposition)
    MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
    MESSAGE_HANDLER(WM_MOUSEHOVER, OnMouseHover)
    MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
    COMMAND_ID_HANDLER(IDM_COPY, OnCopy)
    COMMAND_ID_HANDLER(IDM_PASTE, OnPaste)
    COMMAND_ID_HANDLER(IDM_CUT, OnCut)
    COMMAND_ID_HANDLER(IDM_FIND, OnFind)
    COMMAND_ID_HANDLER(IDM_REPLACE, OnReplace)
END_MSG_MAP()

protected:
// Handler prototypes:
    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnScroll(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnLBtnDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnLBtnUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnDblClk(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnRBtnDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnKeyUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    void CheckForUnindent();
    LRESULT OnImeComposition(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnMouseHover(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnMouseLeave(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

    LRESULT OnCopy(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
    LRESULT OnPaste(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
    LRESULT OnCut(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
    LRESULT OnFind(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
    LRESULT OnReplace(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);

public:
// IPaneWindow interface 
    virtual HWND CreatePaneWindow(HWND hParent, RECT& rc, DWORD dwStyle, DWORD dwExStyle);

public:
// IFindReplaceHost interface
    virtual void FindReplaceDlgDestroyed();
    virtual void FindNext(const char* str, bool up=false);
    virtual void Replace(const char* str0, char* str1, bool up=false);
    virtual void ReplaceAll(const char* str0, char* str1);

public:
    void ReadFromFile(LPCSTR fn);
    bool IsDirty();
    void SetDirty(bool dirty=true);
    void CloseFile();
    void SaveToFile(LPCSTR fn);
    void SetTabSize(UINT size);
    void SetSpaceForTab(bool b);
    void SetSyntaxFile (const char* fn);
    void SetDebugLineNo(unsigned int lineno);
    void InsertTextToCurPos(char* text);
    unsigned int GetCurLine();
    void SetBkPtMgr(IBkPtMgr* mgr);
    void SetDebuggerIF(IDebuggerIF2Editor* pDebugger);

    bool m_bShowLineNumber;
    bool m_bSpaceForTab;

protected:
    HWND m_hParent;
    CTextDoc m_doc;
    CEditStack m_stack;

    UINT m_uFirstShownLine;
    UINT m_uFirstShownChar;
    HFONT m_hFont;
    HBRUSH m_brLineNbr;
    HBRUSH m_brText;
    HBRUSH m_brTextCur;
    HBRUSH m_brDebugLine;
    HBRUSH m_brBreakPoint;
    UINT m_uLineHeight;
    UINT m_uCharWidth;
    
    UINT m_uCurLine;
    UINT m_uCurCol;
    UINT m_uTargetedCol; // Used in Up/down, PgUp/PgDn key.
    UINT m_uTabSize;
    HCURSOR m_hCursor;
    HCURSOR m_hCursorMove;
    HCURSOR m_hCursorCopy;
    bool m_bCaretHidden;
    CTextSelection m_sel; // (line, col)
    CTextSelection m_selFind; // The selection area where "replace" applies. (line, col)
    CTextSelection m_selRestore; // only used in restoring selection after replace operation. (line, col)
    CTextSelection m_selFound; // The position of the text which is previously found. Store (line,index)
    HIMC m_hIMC;
    HMENU m_hEditMenu;
    CFindReplaceDlg* m_dlgFindReplace;
    char* m_strFind;
    CSyntaxConfigArray m_arrSyntax;
    CSyntaxLighter m_syntaxLighter;
    DragMode m_dragMode;
    char m_szFilename[_MAX_PATH];
    UINT m_uDebugLineNo;
    IBkPtMgr* m_pBkPtMgr;
    IDebuggerIF2Editor* m_pDebugger;
    CSimpleTipCtrl      m_ctrlTip;
    POINT               m_ptTip;

protected:
    void DrawLineNumber (HDC dc, UINT uLine, UINT uWidth, RECT* rcLine);
    void DrawLineText (HDC dc, UINT uLine, UINT uLineNbrWidth, RECT* rcLine);
    void DrawColoredText (HDC dc, UINT uLine, RECT* rc);
    void GetSelectedRangeInThisLine(UINT uLine, UINT len, int* firstSelectedIdx, int* lastSelectedIdx);
    void FindSameColorSegment(COLORREF* clr_ar, UINT len, UINT idxStart, UINT* idxEnd, int firstSel, int lastSel, bool& selected);
    void DrawColoredTextSegment(HDC dc, CTextLine* lineobj, UINT uStart, UINT count, COLORREF clr, bool selected, RECT* rcSeg);

    int CalcSBPos (int nBar, WPARAM wParam, long curPos, long upperlimit);
    UINT GetShownLines();
    UINT GetShownChars();
    void SetScrollBars();
    void SetCaretPosAndShow();
    /* Returns the position of Caret, can be outside of the client rect.
     *  if out of client rect, returns false, otherwise ture.
     */
    bool GetCaretPos(int* x, int* y);
    void XY2LineCol(int x, int y, unsigned int* line, unsigned int* col);
    void AdjustViewPort (int xcursor, int ycursor);
    void SetCompositionFont();
    void SetCompositionForm();

    void OnVkHome();
    void OnVkEnd();
    void OnVkPrior();
    void OnVkNext();
    void OnVkLeft();
    void OnVkRight();
    void OnVkUp();
    void OnVkDown();
    void OnVkDel();
    void OnVkF3();
    void OnReturnKey();
    void OnCtrlDown();
    void OnCtrlUp();
    void OnTabKey();
    void OnGoToLineNo();

    void SetCurPosVisible();
    void ChangeCurLineByMouse(LPARAM lParam);
    void GetCurLineRect(RECT* rc);
    void InsertCharToCurPos(char c);
    int InsertImeString();
    void OnBackSpace();
    void DeleteNextChar();
    void DeletePrevChar();
    void DeleteSelected();
    void SelectAll();
    /* FindNextInDoc is a helper routine for FindNext. */
    void FindNextInDoc(const char* str, CTextSelection* pFoundSel, bool up=false);
    /* On success, returns m_strFind. Otherwis, NULL*/
    char* SetFindString(const char* str);
    void AdjustFindSelEndingCol(CTextSelection* pFoundSel, const char* str0, const char* str1);
    int CompareSelection(CTextSelection* sel, const char* str);
    void CopySelectionTo(unsigned int line, unsigned int col);
    void MoveSelectionTo(unsigned int* line, unsigned int* col);
    void ReDo();
    void UnDo();

    bool InHoverRect(const LPPOINT pt);
};

#endif // __TROPHY_EDIT_WINDOW_H__
